import { Checkbox, UploadProps, DatePicker, Form, FormItemProps, Input, InputNumber, InputProps, Radio, RadioGroupProps } from "antd";
import React from "react";
import { FormInstance } from "rc-field-form";
import { SearchProps } from "antd/es/input/Search";
import { TextAreaProps } from "antd/es/input/TextArea";
import { InputNumberProps } from "antd/es/input-number";
import { PickerProps, RangePickerProps as BaseRangePickerProps } from "antd/es/date-picker/generatePicker";
import { Dayjs } from "dayjs";
import { DatePrickRanges } from "@/components/ant-ext/const";
import { HButtonProps } from "@/components/ant-ext/HButton";
import HStaticSelect, { HStaticSelectProps } from "@/components/ant-ext/HStaticSelect";
import { HTreeSelect, HTreeSelectProps } from "@/components/ant-ext/HTreeSelect";
import HUpload from "@/components/ant-ext/HUpload";

type nameValue = { title: string, value: any }


export type HFormItemInnerProps = {
    fieldnames?: FieldName
    placeholder?: string
    disable?: boolean
    dataSource?: nameValue[] | string[] | HStaticSelectProps["dataSource"]
    width?: HStaticSelectProps["width"]
    group?: boolean
    lineNumber?: number
    type?: "upload" | "dateRangePicker" | "datePicker" | "select" | "radio" | "textarea" | "number" | "checkbox" | "treeSelect" | "know" | "input";
}
export type FieldName = {
    label: string
    value: string
    children: string
}


export type HFormItemProps =
    FormItemProps
    & HFormItemInnerProps
    & (
        HButtonProps
        | InputProps
        | SearchProps
        | UploadProps
        | TextAreaProps
        | HStaticSelectProps
        | HTreeSelectProps
        | PickerProps<Dayjs>
        | BaseRangePickerProps<Dayjs>)

type RenderChildren<Values = any> = (form: FormInstance<Values>) => React.ReactNode;
type ChildrenType<Values = any> = RenderChildren<Values> | React.ReactNode;
export default class HFormItem extends React.Component<HFormItemProps, any> {
    state: { factory?: (props: HFormItemProps) => ChildrenType } = {}

    constructor(props: HFormItemProps | Readonly<HFormItemProps>) {
        super(props)
        this.dateRangePicker = this.dateRangePicker.bind(this);
        this.select = this.select.bind(this);
        this.radio = this.radio.bind(this);
        this.textarea = this.textarea.bind(this);
        this.input = this.input.bind(this);
        this.readChildren = this.readChildren.bind(this);
        this.number = this.number.bind(this);
        this.checkbox = this.checkbox.bind(this);
        this.datePicker = this.datePicker.bind(this);
        this.treeSelect = this.treeSelect.bind(this);
        this.state.factory = this.getFactory()
    }

    componentDidUpdate(prevProps: Readonly<HFormItemProps>, prevState: Readonly<any>, snapshot?: any) {
        if (this.props !== prevProps) {
            this.setState({ factory: this.getFactory() })
        }
    }

    getFactory() {
        let { type = "input" } = (this.props as HFormItemInnerProps);
        if (type === "know") {
            return this.readChildren;
        } else {
            switch (type) {
                case "dateRangePicker":
                    return this.dateRangePicker;
                case "datePicker":
                    return this.datePicker;
                case "select":
                    return this.select;
                case "radio":
                    return this.radio;
                case "textarea":
                    return this.textarea;
                case "number":
                    return this.number;
                case "checkbox":
                    return this.checkbox;
                case "treeSelect":
                    return this.treeSelect;
                case "input":
                default:
                    return this.props.children ? undefined : this.input;
            }
        }
    }

    input(props: HFormItemProps) {
        return <Input {...props as InputProps} placeholder={getPlaceholder(props)} />;
    }

    number(props: HFormItemProps) {
        return <InputNumber {...props as InputNumberProps} placeholder={getPlaceholder(props)} />;
    }



    readChildren(props: HFormItemProps) {
        return (props as FormItemProps).children;
    }

    dateRangePicker(props: HFormItemProps) {
        // @ts-ignore
        return <DatePicker.RangePicker {...props as BaseRangePickerProps<Dayjs>} ranges={DatePrickRanges}
            placeholder={getPlaceholder(props)} />;
    }

    datePicker(props: HFormItemProps) {
        return <DatePicker {...props as PickerProps<Dayjs>} placeholder={getPlaceholder(props)} />;
    }


    radio(props: HFormItemProps) {
        const dataSource = props.dataSource as nameValue[];
        return <Radio.Group  {...props as RadioGroupProps}>
            {
                dataSource?.map((p, i) => {
                    let d = p as nameValue
                    return <Radio key={i} value={d.value}>{d.title}</Radio>
                })
            }
        </Radio.Group>
    }

    checkbox(props: HFormItemProps) {
        const { dataSource, lineNumber = 4, group = true } = props as HFormItemInnerProps;
        // @ts-ignore
        let children = dataSource?.map((p, i) => {
            if (typeof p === "string") {
                return <Checkbox style={{ width: "calc((100%)/" + lineNumber, marginLeft: "0px" }} value={p}
                    key={i}>{p}</Checkbox>
            } else {
                return <Checkbox style={{ width: "calc((100%)/" + lineNumber, marginLeft: "0px" }} value={p.value}
                    key={i}>{p.title}</Checkbox>
            }


        })
        if (group) {
            return <Checkbox.Group style={{ width: "100%" }}>
                {
                    children
                }
            </Checkbox.Group>
        } else {
            return children;
        }

    }

    textarea(props: HFormItemProps) {
        return <Input.TextArea {...props as TextAreaProps} placeholder={getPlaceholder(props)} />
    }

    select(props: HFormItemProps) {
        return <HStaticSelect {...props as HStaticSelectProps} placeholder={getPlaceholder(props)} />
    }

    treeSelect(props: HFormItemProps) {
        return <HTreeSelect {...props as HTreeSelectProps} placeholder={getPlaceholder(props)} />
    }


    render() {
        const { factory } = this.state;
        // @ts-ignore
        const { dataSource, treeExpandedKeys, onTreeExpand, addonAfter, maxTagCount, allowClear, children, ...other } = this.props
        return <Form.Item
            {...other}
            rules={getRules(this.props)}
        >
            {children ? children : factory!(this.props)}
        </Form.Item>


    }
}

function getPlaceholder(props: HFormItemProps): string {
    if (props.placeholder) {
        return props.placeholder
    } else {
        if (props.type === "select" || props.type === "treeSelect") {
            return `请选择${props.label}`
        } else {
            return `请输入${props.label}`
        }

    }
}

function getRules(props: HFormItemProps): FormItemProps["rules"] {
    if (props.required) {
        let result = props.rules
        if (result === undefined) {
            result = []
        }
        result.push({ required: true, message: `${props.label}不能为空` })
        return result
    }
    return props.rules
}